import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;

public class Main {

    public static void main(String[] args) throws InterruptedException {
        //引用队列；监控引用与回收
        ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
        String sw="虚引用";
        switch (sw){
            case "软引用":
                Object objSoft = new Object();
//              添加引用: key是被引用对象，value 是引用队列
                SoftReference<Object> softReference = new SoftReference<Object>(objSoft,referenceQueue);
                System.out.println("GC前获取："+softReference.get());
//              手动释放对象并gc
                objSoft=null;
                System.gc();
//              等待回收
                Thread.sleep(1000);
//              查看被引用的对象
                System.out.println("GC后获取："+softReference.get());
//              查看引用队列种的结果
                System.out.println("队列种的结果："+referenceQueue.poll());
       /*       GC前获取：java.lang.Object@1b6d3586
                GC后获取：java.lang.Object@1b6d3586
                队列种的结果：null*/
                break;
            case "弱引用":
                Object objWeak = new Object();
//              添加引用: key是被引用对象，value 是引用队列
                WeakReference<Object> weakReference = new WeakReference<>(objWeak,referenceQueue);
                System.out.println("GC前获取："+weakReference.get());
//              手动释放对象并gc
                objWeak=null;
                System.gc();
//              等待回收
                Thread.sleep(1000);
//              查看被引用的对象
                System.out.println("GC后获取："+weakReference.get());
//              查看引用队列种的结果
                System.out.println("队列种的结果："+referenceQueue.poll());
/*                GC前获取：java.lang.Object@1b6d3586
                GC后获取：null
                队列种的结果：java.lang.ref.WeakReference@4554617c*/
                break;
            case "虚引用":
                Object objPhan = new Object();
                PhantomReference<Object> phantomReference = new PhantomReference<>(objPhan, referenceQueue);
                System.out.println("GC前获取:" + phantomReference.get());
                objPhan = null;
                System.gc();
                //此处的区别是当objPhan的内存被gc回收之前虚引用就会被加入到ReferenceQueue队列中，其他的引用都为当引用被gc掉时候，引用会加入到ReferenceQueue中
                Thread.sleep(1000);
                System.out.println("GC后获取:" + phantomReference.get());
                System.out.println("队列中的结果:" + referenceQueue.poll());
                /*
                * GC前获取:java.lang.Object@61bbe9ba
                * GC后获取:null
                * 队列中的结果:java.lang.ref.WeakReference@610455d6
                * */
                break;

        }
    }
}
